home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 18 / CU Amiga Magazine's Super CD-ROM 18 (1997)(EMAP Images)(GB)[!][issue 1998-01].iso / CUCD / Online / hsc / source / hsclib / uri.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-11-02  |  12.9 KB  |  479 lines

  1. /*
  2.  * This source code is part of hsc, a html-preprocessor,
  3.  * Copyright (C) 1995-1997  Thomas Aglassinger
  4.  *
  5.  * This program is free software; you can redistribute it and/or modify
  6.  * it under the terms of the GNU General Public License as published by
  7.  * the Free Software Foundation; either version 2 of the License, or
  8.  * (at your option) any later version.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program; if not, write to the Free Software
  17.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  */
  20. /*
  21.  * uri.c
  22.  *
  23.  * functions for uri parsing of tag arguments
  24.  *
  25.  * updated:  4-Jul-1997
  26.  * created: 16-Jul-1995
  27.  */
  28.  
  29. #define NOEXTERN_HSCLIB_URI_H
  30.  
  31. #include "ugly/fname.h"
  32.  
  33. #include "hsclib/inc_base.h"
  34. #include "hsclib/idref.h"
  35. #include "hscprj/project.h"
  36. #include "hsclib/uri.h"
  37.  
  38. #define PARENT_URI "../"        /* string for parent dir within URIs */
  39.  
  40. /*
  41.  * conv_path2uri
  42.  *
  43.  * convert a path for local (system-dependant)
  44.  * file system to URI
  45.  */
  46. VOID conv_path2uri(EXPSTR * dest, STRPTR path)
  47. {
  48.     clr_estr(dest);
  49.  
  50. #ifdef AMIGA
  51.     /* replace leading parent directories by "../" */
  52.     while (!strncmp(path, PARENT_DIR, strlen(PARENT_DIR)))
  53.     {
  54.         app_estr(dest, PARENT_URI);
  55.         path += strlen(PARENT_DIR);
  56.     }
  57.  
  58.     while (path[0])
  59.     {
  60.         /* replace all "//" by "../" */
  61.         if ((path[0] == '/') && (path[1] == '/'))
  62.         {
  63.             app_estr(dest, PARENT_URI);
  64.             path += 2;
  65.         }
  66.         else
  67.         {
  68.             app_estrch(dest, path[0]);
  69.             path++;
  70.         }
  71.     }
  72.  
  73. #elif defined RISCOS
  74.     /* simply copy path */
  75.     set_estr(dest, path);
  76.  
  77. #elif defined MSDOS /* dos1 */
  78. #elif (defined NEXTSTEP) || (defined BEOS) || (defined UNIX)
  79.     /* simply copy path */
  80.     set_estr(dest, path);
  81. #else
  82. #error "system not supported: conv_path2uri"
  83. #endif
  84. }
  85.  
  86. /*
  87.  * conv_uri2path
  88.  *
  89.  * convert a uri to a path for local (system-dependant)
  90.  * file system
  91.  */
  92. VOID conv_uri2path(EXPSTR * dest, STRPTR uri, BOOL weenix)
  93. {
  94.     clr_estr(dest);
  95.  
  96. #ifdef AMIGA
  97.     if (weenix)
  98.     {
  99.         /* convert leading "/" to ":" */
  100.         /* convert leading "~" to ":" */
  101.         if (!strncmp(uri, "/", 1)
  102.             || !strncmp(uri, "~/", 2)
  103.             || !strncmp(uri, "~", 1))
  104.         {
  105.             app_estr(dest, ":");
  106.             uri++;
  107.         }
  108.     }
  109.  
  110.     /* convert leading "../" to "/" */
  111.     while (!strncmp(uri, PARENT_URI, strlen(PARENT_URI)))
  112.     {
  113.         app_estr(dest, PARENT_DIR);
  114.         uri += strlen(PARENT_URI);
  115.     }
  116.  
  117.     /* convert inside "../" to "//" */
  118.     while (uri[0])
  119.     {
  120.         if (!strncmp(uri, PARENT_URI, strlen(PARENT_URI)))
  121.         {
  122.             app_estrch(dest, '/');
  123.             uri += strlen(PARENT_URI);
  124.         }
  125.         else
  126.         {
  127.             app_estrch(dest, uri[0]);
  128.             uri++;
  129.         }
  130.     }
  131.  
  132. #elif defined RISCOS
  133.     set_estr(dest, uri);
  134.  
  135. #elif defined MSDOS /* dos2 */
  136. #elif (defined NEXTSTEP) || (defined BEOS) || (defined UNIX)
  137.     set_estr(dest, uri);
  138. #else
  139. #error "system not supported: conv_uri2path"
  140. #endif
  141. }
  142.  
  143. /*
  144.  * uri_kind
  145.  *
  146.  * evaluate kind of uri
  147.  */
  148. URIKIND uri_kind(STRPTR uri)
  149. {
  150.     URIKIND kind = URI_abs;
  151.  
  152.     if (upstrncmp(uri, ABSURI_ID, strlen(ABSURI_ID)))
  153.     {
  154.         if (uri[0] == '/')
  155.             kind = URI_relserv;
  156.         else
  157.         {
  158.             STRPTR colon_pos = strchr(uri, ':');
  159.             STRPTR slash_pos = strchr(uri, '/');
  160.  
  161.             if (colon_pos)
  162.                 if (slash_pos)
  163.                     if (colon_pos < slash_pos)
  164.                         kind = URI_ext;
  165.                     else
  166.                         kind = URI_rel;
  167.                 else
  168.                     kind = URI_ext;
  169.             else
  170.                 kind = URI_rel;
  171.         }
  172.     }
  173.     return (kind);
  174. }
  175.  
  176. /*
  177.  * convert uri to filename in destination-dir
  178.  */
  179. static VOID conv_hscuri2fileNuri(HSCPRC * hp, EXPSTR * dest_uri, EXPSTR * dest_fname, STRPTR uri)
  180. {
  181.     EXPSTR *rel_path = init_estr(32);   /* relative path */
  182.     URIKIND kind = uri_kind(uri);
  183.  
  184.     clr_estr(dest_uri);
  185.     clr_estr(dest_fname);
  186.  
  187.     if  (kind == URI_relserv)
  188.     {
  189.         /* skip "/" in URI */
  190.         STRPTR uri2 = uri + 1;
  191.  
  192.         /* debug */
  193.         D(fprintf(stderr, DHL "exists `%s' [relserv]\n", uri));
  194.  
  195.         /* convert server relative URI to local filename
  196.          * by preceding server_dir */
  197.         conv_uri2path(rel_path, uri2, hp->weenix);
  198.         estrcpy(dest_fname, hp->server_dir);
  199.         estrcat(dest_fname, rel_path);
  200.  
  201.         /* debug */
  202.         D(fprintf(stderr, DHL "  server-dir=`%s'\n", estr2str(hp->server_dir)));
  203.         D(fprintf(stderr, DHL "  rel. path =`%s'\n", estr2str(rel_path)));
  204.  
  205.         /* keep URI untouched */
  206.         set_estr(dest_uri, uri);
  207.     }
  208.     else
  209.     {
  210.         /* convert relative/project uris */
  211.  
  212.         /* if a <BASE HREF="..."> was found before,
  213.          * treat all relative URIs as absolute
  214.          */
  215.         if (hp->docbase_set)
  216.         {
  217.             kind = URI_ext;
  218.         }
  219.  
  220.         /* evaluate kind of URI */
  221.         if (kind == URI_abs)
  222.         {
  223.             uri++;                  /* skip ":" */
  224.         }
  225.  
  226.         if (kind == URI_abs)
  227.         {
  228.             /*
  229.              * parse absolute uri
  230.              */
  231.             D(fprintf(stderr, DHL "exists `%s' [abs]\n", uri));
  232.  
  233.             /* check if local uri exists */
  234.             {
  235.                 EXPSTR *dest_relfname = init_estr(32);
  236.                 conv_uri2path(dest_relfname, uri, hp->weenix);
  237.  
  238.                 estrcpy(dest_fname, hp->destdir);
  239.                 estrcat(dest_fname, dest_relfname);
  240.  
  241.                 del_estr(dest_relfname);
  242.             }
  243.  
  244.             D(fprintf(stderr, DHL "  -> file `%s'\n",
  245.                       estr2str(dest_fname)));
  246.  
  247.             /* create path of destination file */
  248.             estrcpy(dest_uri, hp->reldir);
  249.             app_estr(dest_uri, uri);
  250.  
  251.             get_relfname(rel_path, uri, estr2str(hp->reldir));
  252.             D(fprintf(stderr, DHL "  -> rel. path `%s' (`%s')\n",
  253.                       estr2str(rel_path),
  254.                       estr2str(hp->reldir)));
  255.  
  256.             /* debug */
  257.             D(fprintf(stderr, DHL "  -> real path `%s'\n", uri));
  258.  
  259.             /* convert (filesystem depending) path to uri */
  260.             conv_path2uri(dest_uri, estr2str(rel_path));
  261.         }
  262.         else if (kind == URI_rel)
  263.         {
  264.             /*
  265.              * parse relative uri
  266.              */
  267.             EXPSTR *uri_path = init_estr(32);
  268.  
  269.             /* debug */
  270.             D(fprintf(stderr, DHL "exists `%s' [rel]\n", uri));
  271.  
  272.             /* create local filename */
  273.             conv_uri2path(uri_path, uri, hp->weenix);
  274.             estrcat(dest_fname, hp->destdir);
  275.             estrcat(dest_fname, hp->reldir);
  276.             estrcat(dest_fname, uri_path);
  277.  
  278.             /* create uri (only copy path) */
  279.             set_estr(dest_uri, uri);
  280.  
  281.             del_estr(uri_path);
  282.         }
  283.         else
  284.         {
  285.             set_estr(dest_uri, uri);
  286.             set_estr(dest_fname, "");
  287.         }
  288.     }
  289.  
  290.     /* debug */
  291.     D(
  292.          {
  293.          fprintf(stderr, DHL "  -> real file `%s'\n",
  294.                  estr2str(dest_fname));
  295.          fprintf(stderr, DHL "  -> real uri  `%s'\n",
  296.                  estr2str(dest_uri));
  297.          }
  298.     );
  299.  
  300.     /* free resources */
  301.     del_estr(rel_path);
  302. }
  303.  
  304. VOID conv_hscuri2file(HSCPRC * hp, EXPSTR * dest_fname, STRPTR uri)
  305. {
  306.     EXPSTR *dest_uri = init_estr(64);
  307.     conv_hscuri2fileNuri(hp, dest_uri, dest_fname, uri);
  308.     del_estr(dest_uri);
  309. }
  310.  
  311. /*
  312.  * parse_uri
  313.  *
  314.  * check uri-string for syntatic correctnes;
  315.  * if the uri refers to an local file, convert its absolute
  316.  * path to a relative path and check its existence.
  317.  *
  318.  * uri = "rsrc_type://host.domain:port/pathname#id"
  319.  */
  320. VOID parse_uri(HSCPRC * hp, EXPSTR * dest_uri, STRPTR uri)
  321. {
  322.     STRPTR host = NULL;
  323.     STRPTR port = NULL;
  324.     STRPTR path = NULL;
  325.     STRPTR name = NULL;
  326.  
  327.     clr_estr(dest_uri);
  328.  
  329.     if (uri)
  330.     {
  331.         /* check for valid uri */
  332.         URIKIND kind = uri_kind(uri);
  333.         if ((kind == URI_ext) ||
  334.             ((kind == URI_relserv) && !(estrlen(hp->server_dir))))
  335.         {
  336.             if (kind == URI_ext)
  337.             {
  338.                 /*
  339.                  * check global uri
  340.                  */
  341.                 if (!host)
  342.                 {
  343.                     host = "";
  344.                 }
  345.                 if (!port)
  346.                 {
  347.                     port = "";
  348.                 }
  349.                 if (!host)
  350.                 {
  351.                     host = "";
  352.                 }
  353.  
  354.                 /*
  355.                  * TODO: parse global uris
  356.                  */
  357.             }
  358.             else if (kind == URI_relserv)
  359.             {
  360.                 hsc_message(hp, MSG_SERVER_URI, "server relative URI to %q", uri);
  361.             }
  362.             else
  363.             {
  364.                 panic("what kind of uri now?");
  365.             }
  366.  
  367.             set_estr(dest_uri, uri);
  368.         }
  369.         else
  370.         {
  371.             /*
  372.              * check local uri
  373.              */
  374.  
  375.             /* destination file name that's existence is checked if
  376.              * chkuri is enabled */
  377.             EXPSTR *dest_fname = init_estr(32);
  378.             STRPTR noabsuri = uri;
  379.  
  380.             /* evaluate kind of URI */
  381.             if (kind == URI_abs)
  382.             {
  383.                 noabsuri++;     /* skip ":" */
  384.             }
  385.  
  386.             /* extract path and #name */
  387.             if (noabsuri[0] == '#')
  388.             {
  389.                 path = NULL;
  390.                 name = noabsuri + 1;    /* skip '#' for "#id" */
  391.             }
  392.             else
  393.             {
  394.                 path = strtok(uri, "#");
  395.                 name = strtok(NULL, "");
  396.             }
  397.  
  398.             /* TODO: handle HREF="suck.cgi?arg=..." */
  399.  
  400.             if (path)
  401.             {
  402.                 FILE *exist = NULL;
  403.  
  404.                 /*
  405.                  * check existence of local uri
  406.                  */
  407.                 conv_hscuri2fileNuri(hp, dest_uri, dest_fname, path);
  408.  
  409.                 if (hp->chkuri
  410.                     && !(hsc_get_msg_ignore(hp, MSG_NO_URIPATH)))
  411.                 {
  412.                     exist = fopen(estr2str(dest_fname), "r");
  413.                     if (!exist)
  414.                     {
  415.                         hsc_msg_nouri(hp, estr2str(dest_fname), uri, NULL);
  416.                     }
  417.                     else
  418.                     {
  419.                         fclose(exist);
  420.  
  421.                         /* check id */
  422.                         if (hp->chkid && name)
  423.                         {
  424.                             STRPTR doc_fname = estr2str(dest_fname);
  425.  
  426.                             if (!fnamecmp(hp->project->document->docname,
  427.                                           doc_fname))
  428.                             {
  429.                                 /* filename references current document */
  430.                                 add_local_idref(hp, name);
  431.                             }
  432.                             else
  433.                             {
  434.                                 /* filename reference other document;
  435.                                  * lookup project-data */
  436.                                 switch (check_document_id(hp->project,
  437.                                                           doc_fname, name))
  438.                                 {
  439.                                 case ERR_CDI_OK:
  440.                                     D(fprintf(stderr, DHL "  id ok\n"));
  441.                                     break;
  442.                                 case ERR_CDI_NoID:
  443.                                     hsc_msg_unknown_id(hp, NULL, name);
  444.                                     break;
  445.                                 case ERR_CDI_NoDocumentEntry:
  446.                                     hsc_message(hp, MSG_NO_DOCENTRY,
  447.                                                 "no entry for document %q "
  448.                                               "in project data to check %i",
  449.                                                 estr2str(dest_fname),
  450.                                                 name);
  451.                                     break;
  452.                                 default:
  453.                                     panic("unknown returncode");
  454.                                     break;
  455.                                 }
  456.                             }   /* if fnamecmp */
  457.                         }       /* if hp->chkid */
  458.                     }           /* if exists */
  459.                 }               /* if hp->chkuri */
  460.             }
  461.             else
  462.             {
  463.                 /* check existence ID referencing into current file */
  464.                 if (hp->chkid && name)
  465.                     add_local_idref(hp, name);
  466.             }
  467.  
  468.             /* add #name part */
  469.             if (name)
  470.             {
  471.                 app_estrch(dest_uri, '#');
  472.                 app_estr(dest_uri, name);
  473.             }
  474.             /* free resources */
  475.             del_estr(dest_fname);
  476.         }                       /* else (rsrc) */
  477.     }                           /* if (uri) */
  478. }
  479.